package cn.kgc.spring.factory;

import cn.kgc.spring.annotations.Autowired;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * @author 课工场
 * @date 2024/2/18
 * @description  工厂类 可以实现对象的创建
 */
public class BeanFactory {

    // 初始化容器  存储类加载时创建的bean
    private static HashMap<String,Object> beans = new HashMap<String, Object>();

    // public static UserMapper getUserMapper(){
    //
    //     return new UserMapperOracleImpl();
    // }
    //
    // public static UserService getUserService(){
    //
    //     return new UserServiceImpl();
    // }

   //  初始化实例对象
    static {
       ResourceBundle resourceBundle = ResourceBundle.getBundle("bean");
       //获取配置文件中的key
       Set<String> keySet= resourceBundle.keySet();
       for (String key : keySet) {
           String stringClassName = resourceBundle.getString(key);
           try {
               Class<?> aClass = Class.forName(stringClassName);
               Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
               Object o = declaredConstructor.newInstance();
               // 将对象存储在全局容器中
               beans.put(key,o);
           } catch (Exception e) {
               throw new RuntimeException(e);
           }

       }

       // 遍历容器中所有的对象 实现对象中属性的初始化操作  @Autowired    userServlet :   userServlet 实例
       Set<String> mapKeys = beans.keySet();
       for (String mapKey : mapKeys) {

           // 获取beans容器中的对象
           Object o = beans.get(mapKey);
           // 获取对象中的所有属性
           Class<?> aClass = o.getClass();
           Field[] declaredFields = aClass.getDeclaredFields();
           if (declaredFields!=null){
               // 遍历所有的属性  判定属性上是否有 Autowired注解
               for (Field declaredField : declaredFields) {
                    // 获取属性注解
                   Autowired annotation = declaredField.getAnnotation(Autowired.class);
                   if (annotation!=null){
                       // 根据属性的名字在beans容器中找到对应的值
                       String fieldName = declaredField.getName();
                       Object o1 = beans.get(fieldName);
                       // 初始化属性的值
                       try {
                           // 提升属性操作的权限
                           declaredField.setAccessible(true);
                           declaredField.set(o,o1);
                       } catch (IllegalAccessException e) {
                           throw new RuntimeException(e);
                       }
                   }
               }
           }

       }
   }

    public static <T> T  getBean(Class<T> tClass){

        try {
            Constructor<T> declaredConstructor = tClass.getDeclaredConstructor();
            T t = declaredConstructor.newInstance();
            return  t;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 根据对象的名字获取实例对象
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }

    public static <T> T  getBean(String beanName,Class<T> tClass){
        Object o = beans.get(beanName);
        T cast = tClass.cast(o);
        return cast ;
    }

}
